/**
 * @file cinvocator.h
 * @brief Definizione dell'interfaccia dell'entità Invocator.
 *
 * @date Feb 26, 2012
 * @author Francesco Corvino
 */

#ifndef CINVOCATOR_H_
#define CINVOCATOR_H_

#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "../utilities.h"

#define MAXCOMMANDNAME 25
#define MAXPARAMSLENG 1028

/**
 * @brief Descrizione di un comando.
 *
 * Rappresenta l'interfaccia Command del pattern, tutti i ConcreteCommand devono poter
 * essere adattati a questa struttura definendo una loro funzione <code>void execute()</code>.
 */
typedef struct descCommand {
	// campi obbligatori
	char name[MAXCOMMANDNAME];
	void (*execute)();
	// campi opzionali
	HiddenType descriptorInfo;
	HiddenType typeCommand;
} DescCommand;

/**
 * @brief Descrizione di una richiesta da parte dell'utente.
 *
 * La richiesta non rappresenta ancora un comando, un'utente può utilizzare diversi modi
 * per richiedere un'esecuzione. In base alle politiche adottate per interfacciarsi con l'utente
 *  si possono definire ulteriori argomenti in questa struttura.
 *
 */
typedef struct descRequest {
	char nameCmd[MAXCOMMANDNAME];
	char params[MAXPARAMSLENG];
	pthread_t tid;
	DescCommand * command;
} DescRequest;

/**
 * @brief Definisce i dati dell'applicazione.
 *
 * Esiste una sola istanza di quest'oggetto. Il controllo di quest'istanza
 * viene gestito principalmente dall'invoker, ma i comandi possono farne richiesta
 * per modificarne alcuni valori.
 */
typedef struct descApplication {
	DynArray commands;
	DynArray requests;
	DynArray history;
} DescApplication;

/**
 * @brief descrive le funzionalità esterne di cui necessità la "classe" Invoker.
 *
 * Nella sua operazione principale di invocare i comandi la classe ha bisogno di:
 *  - una funzione per aggiungere le richieste riscontrate dai vari client.
 *  - una funzione per recuperare dal registro i comandi disponibili.
 *  - una funzione per il logging (opzionale).
 *
 */
typedef struct invoker {
	// \brief Dichiarazione della funzione che dovrà recuperare i comandi registrati in memoria.
	DescCommand * (*getCMD)(char*);
	int (*addReq)(DescRequest *req);
	/** \brief Dichiarazione della funzione che dovrà permettere il logging. */
	void (*log)(char*);
} Invoker;

DescCommand * invoke_defineSimpleCMD(const char* name, void (*execute)());

DescCommand * invoke_defineCompleteCMD(const char* name,
		void (*execute)(),
		HiddenType *info, HiddenType *type);

void Invoke_setInvoker(Invoker *value);

void invokeCMD(DescRequest * req);

#endif /* CINVOCATOR_H_ */
